package net.qhzw.vip.qiyu.controller;


import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import net.qhzw.vip.qiyu.dto.*;
import net.qhzw.vip.qiyu.entity.DeliveryMan;
import net.qhzw.vip.qiyu.entity.Order;
import net.qhzw.vip.qiyu.evnet.ConfirmOrderEvent;
import net.qhzw.vip.qiyu.handler.ApiException;
import net.qhzw.vip.qiyu.param.OrderParam;
import net.qhzw.vip.qiyu.param.OrderShopParam;
import net.qhzw.vip.qiyu.param.SubmitOrderParam;
import net.qhzw.vip.qiyu.result.JsonResult;
import net.qhzw.vip.qiyu.service.*;
import net.qhzw.vip.qiyu.util.Arith;
import net.qhzw.vip.qiyu.util.SecurityUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@RestController
@RequestMapping("/p/order")
@Api(tags = "订单接口")
@Slf4j
public class OrderController {

    @Autowired
    private OrderService orderService;

    @Autowired
    private MapperFacade mapperFacade;

    @Autowired
    private SkuService skuService;

    @Autowired
    private ProductService productService;

    @Autowired
    private UserAddrService userAddrService;

    @Autowired
    private BasketService basketService;

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private RabbitTemplate rabbitTemplate;


    /**
     * 生成订单
     */
    @PostMapping("/confirm")
    @ApiOperation(value = "结算，生成订单信息", notes = "传入下单所需要的参数进行下单")
    public JsonResult<ShopCartOrderMergerDto> confirm(@Valid @RequestBody OrderParam orderParam) {
        log.info("下单参数: {}", JSON.toJSONString(orderParam, true));
        Long userId = SecurityUtils.getUserId();
        // 组装获取用户提交的购物车商品项
        List<ShopCartItemDto> shopCartItems = basketService.getShopCartItemsByOrderItems(orderParam.getBasketIds(), orderParam.getOrderItem(), userId);
        if (CollectionUtil.isEmpty(shopCartItems)) {
            throw new ApiException("请选择您需要的商品加入购物车");
        }
        // 根据店铺组装购车中的商品信息，返回每个店铺中的购物车商品信息
        List<ShopCartDto> shopCarts = basketService.getShopCarts(shopCartItems);
        // 将要返回给前端的完整的订单信息
        ShopCartOrderMergerDto shopCartOrderMergerDto = new ShopCartOrderMergerDto();
        ///shopCartOrderMergerDto.setUserAddr(userAddrDto);
        // 所有店铺的订单信息
        List<ShopCartOrderDto> shopCartOrders = new ArrayList<>();
        double actualTotal = 0.0;
        double total = 0.0;
        int totalCount = 0;
        double orderReduce = 0.0;
//        List<CouponOrderDto> coupons = new ArrayList<>();
        for (ShopCartDto shopCart : shopCarts) {
            // 每个店铺的订单信息
            ShopCartOrderDto shopCartOrder = new ShopCartOrderDto();
            shopCartOrder.setShopId(shopCart.getShopId());
            shopCartOrder.setShopName(shopCart.getShopName());
            List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCart.getShopCartItemDiscounts();
            // 店铺中的所有商品项信息
            List<ShopCartItemDto> shopAllShopCartItems = new ArrayList<>();
            for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
                List<ShopCartItemDto> discountShopCartItems = shopCartItemDiscount.getShopCartItems();
                shopAllShopCartItems.addAll(discountShopCartItems);
            }
            shopCartOrder.setShopCartItemDiscounts(shopCartItemDiscounts);
            applicationContext.publishEvent(new ConfirmOrderEvent(shopCartOrder, orderParam, shopAllShopCartItems));
            actualTotal = Arith.add(actualTotal, shopCartOrder.getActualTotal());
            total = Arith.add(total, shopCartOrder.getTotal());
            totalCount = totalCount + shopCartOrder.getTotalCount();
            orderReduce = Arith.add(orderReduce, shopCartOrder.getShopReduce());
            shopCartOrders.add(shopCartOrder);
        }

        shopCartOrderMergerDto.setActualTotal(actualTotal);
        shopCartOrderMergerDto.setTotal(total);
        shopCartOrderMergerDto.setTotalCount(totalCount);
        shopCartOrderMergerDto.setShopCartOrders(shopCartOrders);
        shopCartOrderMergerDto.setOrderReduce(orderReduce);
        shopCartOrderMergerDto.setShippingType(orderParam.getShippingType());
        orderService.putConfirmOrderCache(userId, shopCartOrderMergerDto);
        return JsonResult.ok(shopCartOrderMergerDto);
    }


    @Autowired
    private DeliveryManService deliveryService;

    /**
     * 购物车/立即购买  提交订单,根据店铺拆单
     */
    @PostMapping("/submit")
    @ApiOperation(value = "提交订单，返回支付流水号", notes = "根据传入的参数判断是否为购物车提交订单，同时对购物车进行删除，用户开始进行支付")
    public JsonResult<OrderNumbersDto> submitOrders(@Valid @RequestBody SubmitOrderParam submitOrderParam) {
        Long userId = SecurityUtils.getUserId();
        ShopCartOrderMergerDto mergerOrder = orderService.getConfirmOrderCache(userId);
        DeliveryMan deliveryMan = deliveryService.getById(submitOrderParam.getDeliveryId());
        if (deliveryMan == null || deliveryMan.getPrice() == null) {
            throw new ApiException("配送站点信息有误，请重新选择!");
        }
        mergerOrder.setDeliveryPrice(deliveryMan.getPrice());
        mergerOrder.setDeliveryId(submitOrderParam.getDeliveryId());
        mergerOrder.setDeliveryShopId(deliveryMan.getShopId());
        if (mergerOrder == null) {
            throw new ApiException("订单已过期，请重新下单");
        }
        List<OrderShopParam> orderShopParams = submitOrderParam.getOrderShopParam();
        List<ShopCartOrderDto> shopCartOrders = mergerOrder.getShopCartOrders();
        // 设置备注
        if (CollectionUtil.isNotEmpty(orderShopParams)) {
            for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
                for (OrderShopParam orderShopParam : orderShopParams) {
                    shopCartOrder.setRemarks(orderShopParam.getRemarks());
                    if (Objects.equals(shopCartOrder.getShopId(), orderShopParam.getShopId())) {

                    }
                }
            }
        }
        List<Order> orders = orderService.submit(userId, mergerOrder);
        StringBuilder orderNumbers = new StringBuilder();
        for (Order order : orders) {
            orderNumbers.append(order.getOrderNumber()).append(",");
        }
        orderNumbers.deleteCharAt(orderNumbers.length() - 1);

        boolean isShopCartOrder = false;
        // 移除缓存
        for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
            for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartOrder.getShopCartItemDiscounts()) {
                for (ShopCartItemDto shopCartItem : shopCartItemDiscount.getShopCartItems()) {
                    Long basketId = shopCartItem.getBasketId();
                    if (basketId != null && basketId != 0) {
                        isShopCartOrder = true;
                    }
                    skuService.removeSkuCacheBySkuId(shopCartItem.getSkuId(), shopCartItem.getProdId());
                    productService.removeProductCacheByProdId(shopCartItem.getProdId());
                }
            }
        }
        // 购物车提交订单时(即有购物车ID时)
        if (isShopCartOrder) {
            basketService.removeShopCartItemsCacheByUserId(String.valueOf(userId));
        }
        orderService.removeConfirmOrderCache(userId);
        OrderNumbersDto orderNumbersDto = new OrderNumbersDto(orderNumbers.toString());
        log.info("【当前订单30分钟未支付自动取消, 订单号】: {}", orderNumbersDto.getOrderNumbers());
        //rabbitTemplate.convertAndSend("X", "XA", orderNumbersDto.getOrderNumbers());
        rabbitTemplate.convertAndSend("CANCEL_ORDER_EXCHANGE", "cancelOrder", orderNumbersDto.getOrderNumbers());
        log.info("提交订单, 订单号: {}", orderNumbersDto.getOrderNumbers());
        return JsonResult.ok(orderNumbersDto);
    }

}
